home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Languguage OS 2
/
Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO
/
gnu
/
gnushogi.lha
/
gnushogi-1.1
/
src
/
eval.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-27
|
70KB
|
2,759 lines
/*
* eval.c - C source for GNU SHOGI
*
* Copyright (c) 1993 Matthias Mutz
*
* GNU SHOGI is based on GNU CHESS
*
* Copyright (c) 1988,1989,1990 John Stanback
* Copyright (c) 1992 Free Software Foundation
*
* This file is part of GNU Shogi.
*
* GNU Shogi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* GNU Shogi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Shogi; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "gnushogi.h"
#include "ataks.h"
#ifdef USE_PATTERN
#include "pattern.h"
#endif
#ifdef THINK_C
#include <string.h>
#define bcopy(src,dst,len) memcpy(dst,src,len)
#endif
#if !defined K32SEGMENTS
#include "eval_data1.c"
#endif
int EADD = 0;
int EGET = 0;
#ifdef DEBUG_EVAL
extern short debug_eval;
extern FILE *debug_eval_file;
#endif
static short in_opening_stage = true;
static short behind_in_material[2] = {false, false};
/* distance to enemy king */
static const EnemyKingDistanceBonus[9] =
{0, 20, 15, 8, 5, 3, 1, 0, 0};
/* distance to own king */
static const OwnKingDistanceBonus[9] =
{0, 10, 4, 1, 0, 0, 0, 0, 0};
/* distance to promotion zone */
static const PromotionZoneDistanceBonus[NO_ROWS] =
{0, 0, 0, 0, 4, 8, 10, 10, 10};
/* Bishop mobility bonus indexed by # reachable squares */
static const short BMBLTY[20] =
{0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 16, 16, 16, 16};
/* Rook mobility bonus indexed by # reachable squares */
static const short RMBLTY[20] =
{0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 16, 16, 16, 16};
/* Lance mobility bonus indexed by # reachable squares */
static const short LMBLTY[8] =
{0, 0, 0, 0, 1, 2, 4, 8};
/* penalty for threats to king, indexed by number of such threats */
static const short KTHRT[36] =
{0, -8, -20, -36, -52, -68, -80, -80, -80, -80, -80, -80,
-80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
-80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80};
/* No positional bonus ! */
static const short NoAdvance[NO_SQUARES] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 };
/* Pawn positional bonus (STATIC ROOK vs. STATIC ROOK) */
static const short PawnAdvanceSS[NO_SQUARES] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
3, -2, 15, 4, 6, 1, 6, 8, 3,
0, -5, -5, 0, 0, 0, 5, 10, 5,
0, 0, 0, 0, 0, 0, 0, 0, 10,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 };
#define PawnAdvanceSR PawnAdvanceSS
/* Pawn positional bonus (RANGING ROOK vs. STATIC ROOK) */
static const short PawnAdvanceRS[NO_SQUARES] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
3, -2, 15, 3, 5, 0, -2, -4, 3,
1, 0, 8, 3, 5, 2, 2, -2, -2,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 };
#define PawnAdvanceRR PawnAdvanceRS
/* Lance positional bonus (STATIC ROOK vs. STATIC ROOK) */
short LanceAdvanceSS[NO_SQUARES] =
{ 10, 5, 5, 5, 5, 5, 5, 5, 10,
2, 4, 4, 4, 4, 4, 4, 4, 2,
4, 1, 1, 1, 1, 1, 1, 1, 4,
-2, -2, -2, -2, -2, -2, -2, -2, -2,
-4, -4, -4, -4, -4, -4, -4, -4, -4,
-6, -6, -6, -6, -6, -6, -6, -6, -6,
-8, -8, -8, -8, -8, -8, -8, -8, -8,
-9, -9, -9, -9, -9, -9, -9, -9, -9,
0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* impossible */
#define LanceAdvanceSR LanceAdvanceSS
#define LanceAdvanceRS LanceAdvanceSS
#define LanceAdvanceRR LanceAdvanceRS
/* Knight positional bonus (STATIC ROOK vs. STATIC ROOK) */
short KnightAdvanceSS[NO_SQUARES] =
{-9, 4, 4, 4, 4, 4, 4, 4,-9,
-9, 2, 2, 2, 2, 2, 2, 2,-9,
-9, 1,-10, 1, 1, 1, 1, 1,-9,
-9, 0, 0, 0, 0, 0, 0, 0,-9,
-9, -5, 0, -5, 0,-5, 0,-5,-9
-9, 0, 0, 0, 0, 0, 0, 0,-9,
-9, -9, -9, -9,-9,-9,-9,-9,-9,
0, 0, 0, 0, 0, 0, 0, 0, 0, /* impossible */
0, 0, 0, 0, 0, 0, 0, 0, 0 };/* impossible */
#define KnightAdvanceSR KnightAdvanceSS
#define KnightAdvanceRS KnightAdvanceSS
#define KnightAdvanceRR KnightAdvanceRS
/* Silver positional bonus (STATIC ROOK vs. STATIC ROOK) */
short SilverAdvanceSS[NO_SQUARES] =
{ 0, 0, 0, 0, -6, 0, 0, 0, 0,
0, 8, 3, 4, 0, 3, 2, 0, 0,
0, 0, 10, 0, 0, 6, 6, 4, 0,
0, 0, 0, 0, 4, 0, 4, 5, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 };
/* Silver positional bonus (STATIC ROOK vs. RANGING ROOK) */
short SilverAdvanceSR[NO_SQUARES] =
{ 0, 0, 0, 0, -6, 0, 0, 0, 0,
0, -4, -4, 4, 0, 5, 3, 0, 0,
0, 0, -4, -4, 2, 8, 6, 0, 0,
0, 0, 0, 3, 0, 0, 4, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 };
/* Silver positional bonus (RANGING ROOK vs. STATIC ROOK) */
short SilverAdvanceRS[NO_SQUARES] =
{ -3, 0, 0, 0, 0, 0, 0, 0, -2,
-3, -1, 3, 3, -1, -1, 8, -1, -2,
-2, -2, 0, 5, -1, 9, -2, 5, -3,
0, 0, 5, 2, 5, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 };
#define SilverAdvanceRR SilverAdvanceRS
/* Gold positional bonus (STATIC ROOK vs. STATIC ROOK) */
short GoldAdvanceSS[NO_SQUARES] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 10, 0, 6, 0, 0, 0, 0,
0, 0, 0, 8, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 };
/* Gold positional bonus (STATIC ROOK vs. RANGING ROOK) */
short GoldAdvanceSR[NO_SQUARES] =
{ 0, 0, 0, 10, 0, 0, 0, 0, 0,
0, 0, 0, 0, 6, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 };
/* Gold positional bonus (RANGING ROOK vs. STATIC ROOK) */
short GoldAdvanceRS[NO_SQUARES] =
{ -1, 0, -1, 0, -1, 0, -1, -1, -1,
-1, 0, 4, -1, 4, -1, 8, 0, -1,
-2, -1, 0, -2, 0, 6, 0, -1, -2,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 };
#define GoldAdvanceRR GoldAdvanceRS
/* Bishop positional bonus (STATIC ROOK vs. STATIC ROOK) */
short BishopAdvanceSS[NO_SQUARES] =
{ 3, 0, 0, 0, 0, 0, 0, 0, 3,
0, 4, 0, 8, 0, 0, 0, 3, 0,
0, 0, 6, 0, 0, 0, 4, 0, 0,
0, 2, 0, 3, 0, 3, 0, 2, 0,
0, 0, 2, 0, 3, 0, 0, 0, 0,
0, 2, 0, 3, 0, 3, 0, 2, 0,
0, 0, 3, 0, 0, 0, 3, 0, 0,
0, 3, 0, 0, 0, 0, 0, 3, 0,
3, 0, 0, 0, 0, 0, 0, 0, 3 };
/* Bishop positional bonus (STATIC ROOK vs. RANGING ROOK) */
short BishopAdvanceSR[NO_SQUARES] =
{ 3, 0, 0, 0, 0, 0, 0, 0, 3,
0, 10, 0, 2, 0, 0, 0, 3, 0,
0, 0, 2, 0, 0, 0, 4, 0, 0,
0, 2, 0, 3, 0, 3, 0, 2, 0,
0, 0, 2, 0, 3, 0, 0, 0, 0,
0, 2, 0, 3, 0, 3, 0, 2, 0,
0, 0, 3, 0, 0, 0, 3, 0, 0,
0, 3, 0, 0, 0, 0, 0, 3, 0,
3, 0, 0, 0, 0, 0, 0, 0, 3 };
/* Bishop positional bonus (RANGING ROOK vs. STATIC ROOK) */
short BishopAdvanceRS[NO_SQUARES] =
{ 3, 0, 0, 0, 0, 0, 0, 0, 3,
0, 4, 0, 2, 0, 0, 0, 3, 0,
0, 0, 8, 0, 0, 0, 4, 0, 0,
0, 2, 0, 3, 0, 3, 0, 2, 0,
0, 0, 2, 0, 3, 0, 0, 0, 0,
0, 2, 0, 3, 0, 3, 0, 2, 0,
0, 0, 3, 0, 0, 0, 3, 0, 0,
0, 3, 0, 0, 0, 0, 0, 3, 0,
3, 0, 0, 0, 0, 0, 0, 0, 3 };
#define BishopAdvanceRR BishopAdvanceRS
/* Rook positional bonus (STATIC ROOK vs. STATIC ROOK) */
short RookAdvanceSS[NO_SQUARES] =
{ 2, 0, 0, 0, 0, 0, 0, 4, 2,
2, 0, 0, 0, 0, 0, 0, 8, 2,
-2, 0, 0, 0, 0, 0, 0, 2, -2,
-2, 0, 0, 0, 0, 0, 0, 4, -2,
-2, 0, 0, 0, 0, 0, 0, 2, -2,
-2, 0, 0, 0, 0, 0, 0, 2, -2,
4, 4, 4, 4, 4, 4, 4, 4, 4,
6, 6, 6, 6, 6, 6, 6, 6, 6,
8, 8, 8, 8, 8, 8, 8, 8, 8 };
/* Rook positional bonus (RANING ROOK vs. STATIC ROOK) */
short RookAdvanceRS[NO_SQUARES] =
{ 2, 6, 6, 6, 6, 0, 0, 0, 2,
2, 4, 4, 4, 4, 0, 0, 0, 2,
-2, 2, 3, 3, 3, 0, 0, 0, -2,
-2, 4, 1, 1, 1, 0, 0, 0, -2,
-2, 0, 2, 2, 2, 0, 0, 0, -2,
-2, 0, 0, 0, 0, 0, 0, 0, -2,
4, 4, 4, 4, 4, 4, 4, 4, 4,
6, 6, 6, 6, 6, 6, 6, 6, 6,
8, 8, 8, 8, 8, 8, 8, 8, 8 };
#define RookAdvanceSR RookAdvanceSS
#define RookAdvanceRR RookAdvanceRS
/* King positional bonus inopening stage (STATIC ROOK vs. STATIC ROOK) */
static const short KingAdvanceSS[NO_SQUARES] =
{ 0, -4, 10, 0, -6, -8,-10,-12,-12,
-2, 4, 6, -6, -8, -8,-10,-12,-12,
-6, -6, -6, -8, -8,-10,-11,-12,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12 };
/* King positional bonus inopening stage (STATIC ROOK vs. RANGING ROOK) */
static const short KingAdvanceSR[NO_SQUARES] =
{ 5, -4, -4, -4, -6, -8,-10,-12,-12,
-2, 4, 10, 6, -8, -8,-10,-12,-12,
-6, -6, -6, -8, -8,-10,-11,-12,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12 };
/* King positional bonus inopening stage (RANGING ROOK vs. STATIC ROOK) */
static const short KingAdvanceRS[NO_SQUARES] =
{-12,-12, -8, -6, -4, -8,-10,-12,-12,
-12,-12, -8, -6, -8, 12, 16, 20, -8,
-12,-12, -6, -8, -8,-10, 0, 0, -4,
-12,-12,-12,-12,-12,-12, 0, 0,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12,
-12,-12,-12,-12,-12,-12,-12,-12,-12 };
#define KingAdvanceRR KingAdvanceRS
static short Kfield[2][NO_SQUARES];
char GameType[2] = { UNKNOWN, UNKNOWN };
#ifdef USE_PATTERN
OpeningPattern *attack_pattern[2], *castle_pattern[2];
#endif
short Mpawn[2][NO_SQUARES];
short Msilver[2][NO_SQUARES];
short Mgold[2][NO_SQUARES];
static short *Mlance[2];
static short *Mknight[2];
static short *Mbishop[2];
static short *Mrook[2];
static short Mking[2][NO_SQUARES];
static short c1, c2;
static small_short *PC1, *PC2;
static long *atk1, *atk2;
static long int atak[2][NO_SQUARES];
static short R2NDCOL, EDRNK2B, PWEAKH, PADVNCM, PAWNSHIELD;
static short NADVNCM, SADVNCM, GADVNCM;
static short PMBLTY, BDCLOSED, PSTRONG, P2STRONG;
static short PawnBonus, BishopBonus, RookBonus;
static short KNIGHTPOST, KNIGHTSTRONG, BISHOPSTRONG, KATAK;
static short RHOPN, RHOPNX, BHCLSD, BHCLSDX, KHOPN, KHOPNX, KSFTY;
static short LHOPN, LHOPNX, LPROTECT, NDNGR, LDNGR;
static short SBEFOREG, BXCHG;
static short LXRAY, BRXRAY;
static short KINGED, KINGOD, PROMD;
static short KCASTLD, KMOVD, KADVNCM, OPENOK, OPENWRONG;
static short ATAKD, HUNGP, HUNGX, PINVAL;
#ifdef USE_PATTERN
static short PATTACK, PCASTLE;
#endif
short emtl[2];
short pscore[2];
short tmtl;
#if defined DEBUG8 || defined DEBUG_EVAL
void
debug_position (FILE *D)
{
short r, c, l, side, piece;
fprintf (D, "\n current board is\n\n");
for (piece = pawn; piece <= king; piece++)
if (c = Captured[white][piece])
fprintf(D, "%i%c ",c,pxx[piece]);
fprintf (D, "\n");
for (c = 0; c < NO_COLS; c++)
fprintf (D, " %d", PawnCnt[white][c]);
fprintf (D, "\n\n");
for (r = (NO_ROWS-1); r >= 0; r--)
{
for (c = 0; c < NO_COLS; c++)
{
l = locn (r, c);
if (color[l] == neutral)
fprintf (D, " -");
else if (color[l] == black)
fprintf (D, " %c", qxx[board[l]]);
else
fprintf (D, " %c", pxx[board[l]]);
}
fprintf (D, "\n");
}
fprintf (D, "\n");
for (c = 0; c < NO_COLS; c++)
fprintf (D, " %d", PawnCnt[black][c]);
fprintf (D, "\n");
for (piece = pawn; piece <= king; piece++)
if (c = Captured[black][piece])
fprintf(D, "%i%c ",c,pxx[piece]);
fprintf(D, "\n");
}
void
debug_svalue (FILE *D)
{
short r, c;
for (r = (NO_ROWS-1); r >= 0; r--)
{
for (c = 0; c < NO_COLS; c++)
{
short sq = (r * NO_COLS) + c;
fprintf(D,"%5d",svalue[sq]);
}
fprintf (D, "\n");
}
fprintf (D, "\n");
}
void
debug_table (FILE *D, short *table)
{
short r, c;
for (r = (NO_ROWS-1); r >= 0; r--)
{
for (c = 0; c < NO_COLS; c++)
{
short sq = (r * NO_COLS) + c;
fprintf(D,"%5d",table[sq]);
}
fprintf (D, "\n");
}
fprintf (D, "\n");
}
void
debug_ataks (FILE *D)
{
short side;
for (side = black; side <= white; side++)
{
short l,c,i;
long *atk = atak[side];
fprintf(D, "\n");
for (l = NO_ROWS-1; l >= 0; l--) {
for (c = 0; c < NO_COLS; c++) {
short sq = (l * NO_COLS) + c;
long v = atk[sq];
short n = (short)(v & CNT_MASK);
char s[20];
fprintf(D,"%2d",n);
strcpy(s,"");
if ( v & ctlP ) strcat(s,"P");
if ( v & ctlPp ) strcat(s,"+P");
if ( v & ctlL ) strcat(s,"L");
if ( v & ctlLp ) strcat(s,"+L");
if ( v & ctlN ) strcat(s,"N");
if ( v & ctlNp ) strcat(s,"+N");
if ( v & ctlS ) strcat(s,"S");
if ( v & ctlSp ) strcat(s,"+S");
if ( v & ctlG ) strcat(s,"G");
if ( v & ctlB ) strcat(s,"B");
if ( v & ctlBp ) strcat(s,"+B");
if ( v & ctlR ) strcat(s,"R");
if ( v & ctlRp ) strcat(s,"+R");
if ( v & ctlK ) strcat(s,"K");
fprintf(D,s);
for (i = strlen(s); i < 5; i++)
fprintf(D," ");
fprintf(D," ");
}
fprintf(D,"\n");
}
fprintf(D, "\n");
}
}
#endif
/* ............ POSITIONAL EVALUATION ROUTINES ............ */
/*
* Inputs are:
* pmtl[side] - value of pawns
* mtl[side] - value of all material
* emtl[side] - value of all material - value of pawns - value of king
* hung[side] - count of hung pieces
* Tscore[ply] - search tree score for ply
* ply
* Pscore[ply] - positional score for ply ply
* INCscore - bonus score or penalty for certain moves
* slk - single lone king flag
* Sdepth - search goal depth
* xwndw - evaluation window about alpha/beta
* EWNDW - second evaluation window about alpha/beta
* ChkFlag[ply]- checking piece at level ply or 0 if no check
*/
int
evaluate (register short int side,
register short int ply,
register short int alpha,
register short int beta,
short int INCscore,
short int *InChk) /* output Check flag */
/*
* Compute an estimate of the score by adding the positional score from the
* previous ply to the material difference. If this score falls inside a
* window which is 180 points wider than the alpha-beta window (or within a
* 50 point window during quiescence search) call ScorePosition() to
* determine a score, otherwise return the estimated score.
*/
{
register short evflag, xside;
register short int slk;
short s, sq;
int HEVAL = false;
xside = side ^ 1;
s = -Pscore[ply - 1] + mtl[side] - mtl[xside] + INCscore;
hung[black] = hung[white] = 0;
/* should we use the estimete or score the position */
if ((ply <= Sdepth ||
#ifdef CACHE
(HEVAL = CheckEETable (side)) ||
#endif
((ply == Sdepth + 1 || ply == (Sdepth + 2)) && (s > (alpha - xwndw) && s < (beta + xwndw))) ||
(ply > (Sdepth + 2) && s >= (alpha - EWNDW) && s <= (beta + EWNDW))))
{
/* score the position */
ataks (side, atak[side]);
#ifdef CHECKPIECELIST
if ( board[PieceList[xside][0]] != king )
{
printf("illegal xside PieceList\n");
exit(1);
}
#endif
#if ATAKSCROSSCHECK
{ int b1, b2;
sq = PieceList[xside][0];
b1 = SqAtakd (sq, side);
b2 = Anyatak (side, sq);
if ( b1 != b2 ) {
printf("SqAtakd %d != Anyatak %d for square %d\n",b1,b2,sq);
exit(1);
} else {
if ( b1 )
return ((SCORE_LIMIT+1001) - ply);
}
}
#else
if ( board[sq = PieceList[xside][0]] == king )
if (Anyatak (side, sq))
return ((SCORE_LIMIT+1001) - ply);
#endif
ataks (xside, atak[xside]);
#ifdef CHECKPIECELIST
if ( board[PieceList[side][0]] != king )
{
printf("illegal side PieceList\n");
exit(1);
}
#endif
#if ATAKSCROSSCHECK
{ int b1, b2;
sq = PieceList[side][0];
b1 = SqAtakd (sq, xside);
b2 = Anyatak (xside, sq);
if ( b1 != b2 ) {
printf("SqAtakd %d != Anyatak %d for square %d\n",b1,b2,sq);
exit(1);
} else {
*InChk = b1;
}
}
#else
if ( board[sq = PieceList[side][0]] == king )
*InChk = Anyatak (xside, sq);
else
*InChk = false;
#endif
#if !defined BAREBONES
EvalNodes++;
#endif
if ( flag.tsume )
s = urand () % 50;
else
s = ScorePosition (side);
}
else
{
/* use the estimate but look at check and slk */
short sq;
sq = PieceList[xside][0];
#if CHECKPIECELIST
if ( board[sq] != king )
{
printf("illegal xside 2 PieceList\n");
exit(1);
}
#endif
#if ATAKSCROSSCHECK
{ int b1, b2;
ataks (side, atak[side]);
b1 = SqAtakd (sq, side);
b2 = Anyatak (side, sq);
if ( b1 != b2 ) {
printf("SqAtakd %d != Anyatak %d for square %d\n",b1,b2,sq);
exit(1);
} else {
if ( b1 )
return ((SCORE_LIMIT+1001) - ply);
}
}
#else
if ( board[sq] == king )
if ( SqAtakd (sq, side) )
return ((SCORE_LIMIT+1001) - ply);
#endif
sq = PieceList[side][0];
#if CHECKPIECELIST
if ( board[sq] != king )
{
printf("illegal side 2 PieceList\n");
exit(1);
}
#endif
#if ATAKSCROSSCHECK
{ int b1, b2;
ataks (xside, atak[xside]);
b1 = SqAtakd (sq, xside);
b2 = Anyatak (xside, sq);
if ( b1 != b2 ) {
printf("SqAtakd %d != Anyatak %d for xsquare %d\n",b1,b2,sq);
exit(1);
} else {
*InChk = b1;
}
}
#else
if ( board[sq] == king )
*InChk = SqAtakd (sq, xside);
else
*InChk = false;
#endif
}
Pscore[ply] = s + (mtl[xside] - mtl[side]);
ChkFlag[ply - 1] = ((*InChk) ? Pindex[TOsquare] : 0);
return (s);
}
inline
int
BRLscan (register short int sq, short int *mob)
/*
* Find (promoted) Bishop, (promoted) Rook, and Lance mobility, XRAY attacks, and pins.
* Let BRL be the bishop, rook, or lance.
* Let P be the first piece (no king and no pawn) in a direction and let Q be the second
* piece in the same direction. If Q is an unprotected opponent's piece with
* bigger relative value than BRL, there is a pin if P is an opponent's piece and
* there is an XRAY attack if P is an own piece.
* Increment the hung[] array if a pin is found.
*/
{
register unsigned char *ppos, *pdir;
register short s, mobx;
register short u, pin, ptyp;
short piece, *Kf, rvalue;
mobx = s = 0;
Kf = Kfield[c1];
piece = board[sq];
rvalue = relative_value[piece];
ptyp = ptype[c1][unpromoted[piece]];
ppos = (*nextpos[ptyp])[sq];
pdir = (*nextdir[ptyp])[sq];
u = ppos[sq];
pin = -1; /* start new direction */
do
{
s += Kf[u];
#ifdef DEBUG_EVAL
if ( debug_eval && Kf[u] != 0 )
fprintf(debug_eval_file,"add %d for controlling square near enemy king\n",Kf[u]);
#endif
if (color[u] == neutral)
{
mobx++;
if (ppos[u] == pdir[u])
pin = -1; /* oops new direction */
u = ppos[u];
}
else
{ /* there is a piece in current direction */
if (pin < 0)
{ /* it's the first piece in the current direction */
if (piece == lance && color[u] == c1 )
{
s += LPROTECT;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for lance protection\n",LPROTECT);
#endif
}
else if ( piece == bishop && board[u] == pawn )
{
if ( color[u] == c1 )
{
s += 2*BHCLSD;
#ifdef DEBUG_EVAL
if (debug_eval )
fprintf(debug_eval_file,"add %d for own pawn in bishops direction\n",2*BHCLSD);
#endif
}
else
{
s += 2*BHCLSDX;
#ifdef DEBUG_EVAL
if (debug_eval )
fprintf(debug_eval_file,"add %d for opponents pawn in bishops direction\n",2*BHCLSDX);
#endif
}
}
if (board[u] == pawn || board[u] == king)
u = pdir[u];
else
{
if (ppos[u] != pdir[u])
pin = u; /* not on the edge and on to find a pin */
u = ppos[u];
}
}
else
{
/* it's the second piece in the current direction */
if ( piece == bishop && board[u] == pawn )
{
if ( color[u] == c1 )
{
s += BHCLSD;
#ifdef DEBUG_EVAL
if (debug_eval )
fprintf(debug_eval_file,"add %d for own pawn in bishops direction\n",BHCLSD);
#endif
}
else
{
s += BHCLSDX;
#ifdef DEBUG_EVAL
if (debug_eval )
fprintf(debug_eval_file,"add %d for opponents pawn in bishops direction\n",BHCLSDX);
#endif
}
}
if ((color[u] == c2) &&
(relative_value[board[u]] > rvalue || atk2[u] == 0))
{
if (color[pin] == c2)
{
s += PINVAL;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for pin\n",PINVAL);
#endif
if (atk2[pin] == 0 || atk1[pin] > control[board[pin]] + 1)
++hung[c2];
}
else
if ( piece == lance ) {
s += LXRAY;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"lance xray: %d\n",LXRAY);
#endif
} else {
s += BRXRAY;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"bishop/rook xray: %d\n",BRXRAY);
#endif
}
}
pin = -1; /* new direction */
u = pdir[u];
}
}
}
while (u != sq);
*mob = mobx;
return s;
}
inline
short int
KingScan (register short int sq)
/*
* Assign penalties if king can be threatened by checks, if squares near the
* king are controlled by the enemy (especially the queen), or if there are
* no pawns near the king. The following must be true: board[sq] == king c1
* == color[sq] c2 == otherside[c1]
*/
#define ScoreThreat \
if (color[u] != c2)\
if (atk1[u] == 0 || (atk2[u] & CNT_MASK) > 1) ++cnt;\
else s -= 3
{
register short cnt;
register unsigned char *ppos, *pdir;
register short int s;
register short u, ptyp;
short int ok;
s = 0;
cnt = 0;
{ short p;
for ( p = pawn; p < king; p++ )
if ( HasPiece[c2][p] )
{ short ptyp = ptype[c2][p];
ppos = (*nextpos[ptyp])[sq];
pdir = (*nextdir[ptyp])[sq];
u = ppos[sq];
do
{
if (atk2[u] & control[p])
ScoreThreat;
u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
}
while (u != sq);
}
}
s += (KSFTY * KTHRT[cnt]);
cnt = 0;
ok = false;
ptyp = ptype[black][king];
pdir = (*nextpos[ptyp])[sq];
u = pdir[sq];
do
{
if (board[u] == pawn)
ok = true;
if (atk2[u] > atk1[u])
{
++cnt;
}
u = pdir[u];
}
while (u != sq);
if (!ok)
s -= KSFTY;
if (cnt > 1)
s -= KSFTY;
return (s);
}
inline
int
trapped (register short int sq)
/*
* See if the attacked piece has unattacked squares to move to. The following
* must be true: c1 == color[sq] c2 == otherside[c1]
*/
{
register short u, ptyp;
register unsigned char *ppos, *pdir;
register short int piece;
piece = board[sq];
ptyp = ptype[c1][piece];
ppos = (*nextpos[ptyp])[sq];
pdir = (*nextdir[ptyp])[sq];
{
short rvalue = relative_value[piece];
u = ppos[sq];
do
{
if (color[u] != c1)
if (atk2[u] == 0 || relative_value[board[u]] >= rvalue)
return (false);
u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
}
while (u != sq);
}
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"piece is trapped\n");
#endif
return (true);
}
#define mirrored(sq) (NO_SQUARES-1-sq)
#define csquare(side,sq) ((side==black)?sq:mirrored(sq))
#define crow(side,sq) row(csquare(side,sq))
#define ccolumn(side,sq) column(csquare(side,sq))
inline
static short on_csquare(short side,short piece,short square)
{ short sq;
return(board[sq=csquare(side,square)]==piece && color[sq]==side);
}
inline
static short on_column(short side,short piece,short c)
{ short sq;
for (sq = c; sq < NO_SQUARES; sq+=9)
if (on_csquare(side,piece,sq))
return(true);
return(false);
}
#define empty_square(side,square) (board[csquare(side,square)]==no_piece)
inline
static short on_left_side(short side,short piece)
{ short c;
for (c=0; c<4; c++)
if (on_column(side,piece,c))
return(true);
return(false);
}
inline
static short on_right_side(short side,short piece)
{ short c;
for (c=5; c<NO_COLS; c++)
if (on_column(side,piece,c))
return(true);
return(false);
}
/* Distance bonus */
inline
static
short AddEnemyKingDistanceBonus (short sq)
{ short s = 0;
/* near enemy king */
if ( !in_opening_stage || behind_in_material[c1] )
if ( distance(sq,OwnKing) > 2 )
s = EnemyKingDistanceBonus[distance(sq,EnemyKing)];
return(s);
}
inline
static
short AddOwnKingDistanceBonus (short sq)
{ short s = 0;
/* near own king */
if ( !in_opening_stage || behind_in_material[c1] )
s = OwnKingDistanceBonus[distance(sq,OwnKing)];
return(s);
}
inline
static
short AddPromotionZoneDistanceBonus (short sq)
{ short s = 0;
/* near promotion zone */
if ( !in_opening_stage )
s = PromotionZoneDistanceBonus[crow(c1,sq)];
return(s);
}
static inline int
PawnValue (register short int sq, short int side)
/*
* Calculate the positional value for a pawn on 'sq'.
*/
{
register short s;
long a1, a2;
s = Mpawn[c1][csquare(c1,sq)];
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"inital value [%d] for pawn on %c%c: %d\n",
csquare(c1,sq), cxx[column(sq)], rxx[row(sq)], s);
#endif
s += PROMD * AddPromotionZoneDistanceBonus(sq);
/* pawn mobility */
{
short u, ptyp;
register unsigned char *pdir;
ptyp = ptype[c1][pawn];
pdir = (*nextdir[ptyp])[sq];
u = pdir[sq];
if ( u != sq )
if ( color[u] == neutral ) {
s += PMBLTY;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for mobility\n", PMBLTY);
#endif
}
}
a1 = atk1[sq];
a2 = atk2[sq];
if (a2 > 0)
{
if (a1 == 0 || a2 > ctlP + 1)
{
s += HUNGP;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for hung\n", HUNGP);
#endif
if (trapped (sq)) {
hung[c1] += 2;
}
hung[c1]++;
}
else if (a2 > a1) {
s += ATAKD;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for atacked piece\n",ATAKD);
#endif
}
}
if ( a1 > 0 ) {
s += (a1 & CNT_MASK);
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for protected piece\n",(a1 & CNT_MASK));
#endif
}
if ( sq == csquare(c1,20) ) {
s += BDCLOSED;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for closed bishops diagonal\n",BDCLOSED);
#endif
}
if ( (a1 & ((ctlR | ctlRp) | ctlL)) ) {
s += PSTRONG;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for rook/lance-supported pawn\n", PSTRONG);
#endif
}
if ( in_opening_stage )
if ( crow(c1,sq) == 2 ) /* pawn on 3d rank */
if ( Mvboard[(c1==black)?(sq+36):(sq-36)] )
{ /* opposing pawn has been moved (even column == (sq & 1)) */
s -= (sq & 1) ? PMBLTY : (3*PMBLTY)/2;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for opposing pawn pushed\n",
-((sq & 1) ? PMBLTY : (3*PMBLTY)/2));
#endif
}
if ( sq == csquare(c1,43) )
{
if ( (atk2[csquare(c1,52)] & CNT_MASK) < 2 ) {
s += P2STRONG;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for attacking pawn on 2nd col\n",
P2STRONG);
#endif
}
}
return (s);
}
static inline int
LanceValue (register short int sq, short int side)
/*
* Calculate the positional value for a lance on 'sq'.
*/
{
register short s;
register short fyle;
short mob;
long a1, a2;
short checked_trapped = false;
s = Mlance[c1][csquare(c1,sq)];
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"inital value [%d] for lance on %c%c: %d\n",
csquare(c1,sq), cxx[column(sq)], rxx[row(sq)], s);
#endif
s += KINGOD * AddOwnKingDistanceBonus(sq);
s += BRLscan (sq, &mob);
s += LMBLTY[mob];
fyle = column (sq);
if (PC1[fyle] == 0)
{
s += LHOPN;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for no own pawn on lance file\n",LHOPN);
#endif
}
if (PC2[fyle] == 0)
{
s += LHOPNX;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for no opponents pawn on lance file\n",LHOPNX);
#endif
}
a2 = atk2[sq];
a1 = atk1[sq];
if (a2 > 0)
{
if (a1 == 0 || a2 > ctlL + 1)
{
s += HUNGP;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for hung\n", HUNGP);
#endif
if (trapped (sq))
hung[c1] += 2;
hung[c1]++;
}
else if (a2 >= ctlL || a1 < ctlP)
{
s += ATAKD;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for atacked piece\n",ATAKD);
#endif
}
}
if ( !checked_trapped && crow(c1,sq) > 2 )
{
if (trapped (sq))
{
s += LDNGR;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for lance in danger\n",LDNGR);
#endif
}
else
{
s += LDNGR / 4;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for lance in danger\n",LDNGR / 4);
#endif
}
}
if ( a1 > 0 ) {
s += (a1 & CNT_MASK);
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for protected piece\n",(a1 & CNT_MASK));
#endif
}
return (s);
}
static inline int
KnightValue (register short int sq, short int side)
/*
* Calculate the positional value for a knight on 'sq'.
*/
{
register short s;
long a1, a2;
short checked_trapped = false;
s = Mknight[c1][csquare(c1,sq)];
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"inital value [%d] for knight on %c%c: %d\n",
csquare(c1,sq), cxx[column(sq)], rxx[row(sq)], s);
#endif
s += PROMD * AddPromotionZoneDistanceBonus(sq);
s += KINGOD * AddOwnKingDistanceBonus(sq);
a2 = atk2[sq];
a1 = atk1[sq];
if (a2 > 0)
{
if (a1 == 0 || a2 > ctlN + 1)
{
s += HUNGP;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for hung\n", HUNGP);
#endif
checked_trapped = true;
if (trapped (sq))
hung[c1] += 2;
hung[c1]++;
}
else if (a2 >= ctlN || a1 < ctlP)
{
s += ATAKD;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for atacked piece\n",ATAKD);
#endif
}
}
if ( !checked_trapped && crow(c1,sq) > 2 )
{
if (trapped (sq))
{
s += NDNGR;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for knight in danger\n",NDNGR);
#endif
}
else
{
s += NDNGR / 4;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for knight in danger\n",NDNGR / 4);
#endif
}
}
if ( a1 > 0 ) {
s += (a1 & CNT_MASK);
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for protected piece\n",(a1 & CNT_MASK));
#endif
}
return (s);
}
static inline int
SilverValue (register short int sq, short int side)
/*
* Calculate the positional value for a silver on 'sq'.
*/
{
register short s;
long a1, a2;
s = Msilver[c1][csquare(c1,sq)];
s += KINGED * AddEnemyKingDistanceBonus(sq);
s += KINGOD * AddOwnKingDistanceBonus(sq);
a2 = atk2[sq];
a1 = atk1[sq];
if (a2 > 0)
{
if (a1 == 0 || a2 > ctlS + 1)
{
s += HUNGP;
if (trapped (sq))
hung[c1] += 2;
hung[c1]++;
}
else if (a2 >= ctlS || a1 < ctlP)
s += ATAKD;
}
if ( a1 > 0 )
s += (a1 & CNT_MASK);
if ( in_opening_stage && GameType[c1] == STATIC_ROOK )
if ( csquare(c1,sq) == 12 )
{
short csq;
if ( board[csq = csquare(c1,20)] == bishop && color[csq] == c1 )
{
s += 2 * OPENWRONG;
}
}
/* proverb: silver before gold */
{
short u, ptyp;
register unsigned char *pdir;
ptyp = ptype[c2][pawn];
pdir = (*nextdir[ptyp])[sq];
u = pdir[sq];
if ( u != sq )
if ( color[u] == c1 && board[u] == gold )
s += SBEFOREG;
}
return (s);
}
static inline int
GoldValue (register short int sq, short int side)
/*
* Calculate the positional value for a gold on 'sq'.
*/
{
register short s;
long a1, a2;
s = Mgold[c1][csquare(c1,sq)];
s += KINGED * AddEnemyKingDistanceBonus(sq);
s += KINGOD * AddOwnKingDistanceBonus(sq);
a2 = atk2[sq];
a1 = atk1[sq];
if (a2 > 0)
{
if (a1 == 0 || a2 > ctlG + 1)
{
s += HUNGP;
if (trapped (sq))
hung[c1] += 2;
hung[c1]++;
}
else if (a2 >= ctlG || a1 < ctlP)
s += ATAKD;
}
if ( a1 > 0 )
s += (a1 & CNT_MASK);
return (s);
}
static inline int
BishopValue (register short int sq, short int side)
/*
* Calculate the positional value for a bishop on 'sq'.
*/
{
register short s;
long a2, a1;
short mob;
s = Mbishop[c1][csquare(c1,sq)];
#ifdef DEBUG_EVAL
if (debug_eval )
fprintf(debug_eval_file,"inital value [%d] for bishop on %c%c: %d\n",
csquare(c1,sq), cxx[column(sq)], rxx[row(sq)], s);
#endif
s += BRLscan (sq, &mob);
s += BMBLTY[mob];
a2 = atk2[sq];
if (a2 > 0)
{
a1 = atk1[sq];
if (a1 == 0 || a2 > ctlB + 1)
{
s += HUNGP;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for hung\n", HUNGP);
#endif
if (trapped (sq))
hung[c1] += 2;
hung[c1]++;
}
else if (a2 >= ctlB || a1 < ctlP)
{
s += ATAKD;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for atacked piece\n",ATAKD);
#endif
}
}
if ( in_opening_stage )
{
if ( GameType[c1] == RANGING_ROOK )
{
/* Bishops diagonal should not be open */
if ( !on_csquare(c1,pawn,30) )
s += OPENWRONG;
}
else if ( GameType[c2] == RANGING_ROOK )
{
/* Bishops diagonal should be open */
if ( csquare(c1,sq) == 20 && on_csquare(c1,pawn,30) )
s += OPENWRONG;
}
}
return (s);
}
static inline int
RookValue (register short int sq, short int side)
/*
* Calculate the positional value for a rook on 'sq'.
*/
{
register short s;
register short fyle;
long a2, a1;
short mob, r, c;
s = Mrook[c1][csquare(c1,sq)];
#ifdef DEBUG_EVAL
if (debug_eval )
fprintf(debug_eval_file,"inital value [%d] for rook on %c%c: %d\n",
csquare(c1,sq), cxx[column(sq)], rxx[row(sq)], s);
#endif
s += BRLscan (sq, &mob);
s += RMBLTY[mob];
#ifdef DEBUG_EVAL
if ( debug_eval && (c = RMBLTY[mob]) != 0 ) {
s += c;
fprintf(debug_eval_file,"adding rook for mobility %d value %d\n",mob,c);
}
#endif
fyle = column (sq);
if (PC1[fyle] == 0) {
s += RHOPN; /* no own pawn on rook file */
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for no own pawn on rook file\n",RHOPN);
#endif
}
if (PC2[fyle] == 0) {
s += RHOPNX; /* no enemy pawn on rook file */
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for no enemy pawn on rook file\n",RHOPNX);
#endif
}
a2 = atk2[sq];
if (a2 > 0)
{
a1 = atk1[sq];
if (a1 == 0 || a2 > ctlR + 1)
{
s += HUNGP;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for hung\n", HUNGP);
#endif
if (trapped (sq)) {
hung[c1] += 2;
}
hung[c1]++;
}
else if (a2 >= ctlR || a1 < ctlP)
{
s += ATAKD;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for atacked piece\n",ATAKD);
#endif
}
}
if ( in_opening_stage ) {
#ifdef DEBUG_EVAL
short s0 = s;
#endif
if ( GameType[c1] == STATIC_ROOK )
{
short c = ccolumn(c1,sq);
/* Bonus for rook on 8th file */
if ( c == 7 ) {
s += R2NDCOL;
}
/* Bonus for rook on right side, malus for rook on left side */
c = 4 - c;
if ( c < 0 ) {
s += c + c + OPENOK;
} else if ( c >= 0 ) {
s += c + c + OPENWRONG;
}
}
else if ( GameType[c1] == RANGING_ROOK )
{
/* Bonus for rook on left side and bishops diagonal closed, malus otherwise. */
short c;
c = 4 - ccolumn(c1,sq);
if ( c >= 0 ) {
/* Bishops diagonal should not be open */
if ( on_csquare(c1,pawn,30) )
s += OPENOK;
else
s += c + c + OPENWRONG;
} else if ( c < 0 ) {
s += c + c + OPENWRONG;
/* Malus for king not on initial square */
if ( !on_csquare(side,king,4) ) {
s += 4 * OPENWRONG;
}
}
}
#ifdef DEBUG_EVAL
if ( debug_eval && (s0 != s) )
fprintf(debug_eval_file,"adding %d for opening\n",(s-s0));
#endif
}
return (s);
}
static inline int
PPawnValue (register short int sq, short int side)
/*
* Calculate the positional value for a promoted pawn on 'sq'.
*/
{
register short s;
long a2, a1;
s = 0;
s += (KINGED + 2) * AddEnemyKingDistanceBonus(sq);
a2 = atk2[sq];
if (a2 > 0)
{
a1 = atk1[sq];
if (a1 == 0 || a2 > ctlPp + 1)
{
s += HUNGP;
if (trapped (sq))
hung[c1] += 2;
hung[c1]++;
}
else if (a2 >= ctlPp || a1 < ctlP)
s += ATAKD;
}
return (s);
}
static inline int
PLanceValue (register short int sq, short int side)
/*
* Calculate the positional value for a promoted lance on 'sq'.
*/
{
register short s;
long a2, a1;
s = 0;
s += (KINGED + 1) * AddEnemyKingDistanceBonus(sq);
a2 = atk2[sq];
if (a2 > 0)
{
a1 = atk1[sq];
if (a1 == 0 || a2 > ctlLp + 1)
{
s += HUNGP;
if (trapped (sq))
hung[c1] += 2;
hung[c1]++;
}
else if (a2 >= ctlLp || a1 < ctlP)
s += ATAKD;
}
return (s);
}
static inline int
PKnightValue (register short int sq, short int side)
/*
* Calculate the positional value for a promoted knight on 'sq'.
*/
{
register short s;
long a2, a1;
s = 0;
s += (KINGED + 1 ) * AddEnemyKingDistanceBonus(sq);
a2 = atk2[sq];
if (a2 > 0)
{
a1 = atk1[sq];
if (a1 == 0 || a2 > ctlNp + 1)
{
s += HUNGP;
if (trapped (sq))
hung[c1] += 2;
hung[c1]++;
}
else if (a2 >= ctlNp || a1 < ctlP)
s += ATAKD;
}
return (s);
}
static inline int
PSilverValue (register short int sq, short int side)
/*
* Calculate the positional value for a promoted silver on 'sq'.
*/
{
register short s;
long a2, a1;
s = 0;
s += (KINGED + 1) * AddEnemyKingDistanceBonus(sq);
a2 = atk2[sq];
if (a2 > 0)
{
a1 = atk1[sq];
if (a1 == 0 || a2 > ctlSp + 1)
{
s += HUNGP;
if (trapped (sq))
hung[c1] += 2;
hung[c1]++;
}
else if (a2 >= ctlSp || a1 < ctlP)
s += ATAKD;
}
return (s);
}
static inline int
PBishopValue (register short int sq, short int side)
/*
* Calculate the positional value for a promoted bishop on 'sq'.
*/
{
register short s;
long a2, a1;
short mob;
s = Mbishop[c1][csquare(c1,sq)];
if ( InPromotionZone(c1,sq) )
s += KINGED * AddEnemyKingDistanceBonus(sq);
s += BRLscan (sq, &mob);
s += BMBLTY[mob];
a2 = atk2[sq];
if (a2 > 0)
{
a1 = atk1[sq];
if (a1 == 0 || a2 > ctlBp + 1)
{
s += HUNGP;
if (trapped (sq))
hung[c1] += 2;
hung[c1]++;
}
else if (a2 >= ctlBp || a1 < ctlP)
s += ATAKD;
}
return (s);
}
static inline int
PRookValue (register short int sq, short int side)
/*
* Calculate the positional value for a promoted rook on 'sq'.
*/
{
register short s;
register short fyle;
long a2, a1;
short mob;
s = Mrook[c1][csquare(c1,sq)];
if ( InPromotionZone(c1,sq) )
s += KINGED * AddEnemyKingDistanceBonus(sq);
s += BRLscan (sq, &mob);
s += RMBLTY[mob];
fyle = column (sq);
if (PC1[fyle] == 0)
s += RHOPN;
if (PC2[fyle] == 0)
s += RHOPNX;
a2 = atk2[sq];
if (a2 > 0)
{
a1 = atk1[sq];
if (a1 == 0 || a2 > ctlRp + 1)
{
s += HUNGP;
if (trapped (sq))
hung[c1] += 2;
hung[c1]++;
}
else if (a2 >= ctlRp || a1 < ctlP)
s += ATAKD;
}
return (s);
}
static inline int
KingValue (register short int sq, short int side)
/*
* Calculate the positional value for a king on 'sq'.
*/
{
register short s;
register short fyle;
long a2, a1;
s = Mking[c1][csquare(c1,sq)];
#ifdef DEBUG_EVAL
if (debug_eval )
fprintf(debug_eval_file,"inital value [%d] for king on %c%c: %d\n",
csquare(c1,sq), cxx[column(sq)], rxx[row(sq)], s);
#endif
if (KSFTY > 0)
s += KingScan (sq);
if (Mvboard[kingP[c1]])
s += KMOVD;
fyle = column (sq);
if (PC1[fyle] == 0)
{
s += KHOPN;
#ifdef DEBUG_EVAL
if (debug_eval )
fprintf(debug_eval_file,"adding %d for now own pawn on file\n",
KHOPN);
#endif
}
if (PC2[fyle] == 0)
{
s += KHOPNX;
#ifdef DEBUG_EVAL
if (debug_eval )
fprintf(debug_eval_file,"adding %d for now opponents pawn on file\n",
KHOPNX);
#endif
}
a2 = atk2[sq];
if (a2 > 0)
{
a1 = atk1[sq];
if (a1 == 0 || a2 > ctlK + 1)
{
s += HUNGP;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for hung\n", HUNGP);
#endif
++hung[c1];
}
else
{
s += ATAKD;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for attacked piece\n",
ATAKD);
#endif
}
}
if ( in_opening_stage ) {
/* king has moved */
if ( GameType[c1] == STATIC_ROOK )
{
/* Malus for king on right side or fifth file */
short c;
c = 4 - ccolumn(c1,sq);
if ( c < 0 || (c == 0 && sq != kingP[c1]) ) {
s += c + c + OPENWRONG;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"add %d for king on right side (Static)\n",
c + c + OPENWRONG);
#endif
}
}
else if ( GameType[c1] == RANGING_ROOK )
{
/* Malusalus for king on left side or fifth file */
short c;
c = 4 - ccolumn(c1,sq);
if ( c > 0 || (c == 0 && sq != kingP[c1]) ) {
s += c + c + OPENWRONG;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"add %d for king on left side (Ranging)\n",
c + c + OPENWRONG);
#endif
}
/* Malus for king moved before rook switch */
if ( sq != kingP[c1] )
if ( on_csquare(side,rook,16) ) {
s += 4 * OPENWRONG;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"add %d for king moved before rook switch (Ranging)\n",
4 * OPENWRONG);
#endif
}
/* Malus for defending general moved before king switch to right side */
if ( ccolumn(c1,sq) < 6 )
if ( Mvboard[csquare(c1,5)] || Mvboard[csquare(c1,6)] ) {
s += 2 * OPENWRONG;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,
"add %d for defending general moved before king switch (Ranging)\n",
2 * OPENWRONG);
#endif
}
}
}
return (s);
}
#ifdef USE_PATTERN
short
ScorePatternDistance (register short int side)
/*
* Score distance to pattern regarding the game type which side plays.
*/
{
short ds, s = 0;
OpeningPattern *p = NULL;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"scoring castle pattern distance for PCASTLE=%d\n",
PCASTLE);
#endif
if ( PCASTLE != 0 && ((p = castle_pattern[side]) != NULL) )
{
ds = board_to_pattern_distance(side,p,PCASTLE,GameCnt);
if ( ds != 0) {
s += ds;
#ifdef DEBUG_EVAL
if ( debug_eval && ds != 0 )
fprintf(debug_eval_file,
"add %d for max gain of %s to reachable castle patterns %s\n",
ds, ColorStr[side], p->name);
#endif
};
}
#ifdef DEBUG_EVAL
else if ( debug_eval && p == NULL )
fprintf(debug_eval_file,"no castle pattern for %s\n",ColorStr[side]);
#endif
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"scoring attack pattern distance for PATTACK=%d\n",
PATTACK);
#endif
if ( PATTACK != 0 && ((p = attack_pattern[side]) != NULL) )
{
ds = board_to_pattern_distance(side,p,PATTACK,GameCnt);
if ( ds != 0 ) {
s += ds;
#ifdef DEBUG_EVAL
if ( debug_eval && ds != 0 )
fprintf(debug_eval_file,
"add %d for max gain of %s to reachable attack patterns %s\n",
ds, ColorStr[side], p->name);
#endif
}
}
#ifdef DEBUG_EVAL
else if ( debug_eval && p == NULL )
fprintf(debug_eval_file,"no attack pattern for %s\n",ColorStr[side]);
#endif
return(s);
}
static
void
UpdatePatterns (short int side, short int GameCnt)
/*
* Determine castle and attack pattern which should be reached next.
* Only patterns are considered, which have not been reached yet.
*/
{
char s[12];
short xside = side ^ 1;
OpeningPattern *p;
#ifdef DEBUG_EVAL
short i;
PatternSequence *sequence;
#endif
strcpy(s,"CASTLE_?_?");
s[7] = GameType[side];
s[9] = GameType[xside];
castle_pattern[side] = p = locate_opening_pattern(side,s,GameCnt);
#ifdef DEBUG_EVAL
if ( debug_eval )
if (p != NULL )
{
fprintf(debug_eval_file,"castle pattern of %s is %s\n",
ColorStr[side], p->name);
fprintf(debug_eval_file,"reachable patterns: ");
for (i=0,sequence=p->sequence; i<p->n; i++,sequence=sequence->next_pattern)
if ( sequence->distance[side] != CANNOT_REACH )
fprintf(debug_eval_file,"%d ",i);
fprintf(debug_eval_file,"\n");
}
else
{
fprintf(debug_eval_file,"no castle pattern %s for %s\n",
s, ColorStr[side]);
}
#endif
strcpy(s,"ATTACK_?_?");
s[7] = GameType[side];
s[9] = GameType[xside];
attack_pattern[side] = p = locate_opening_pattern(side,s,GameCnt);
#ifdef DEBUG_EVAL
if ( debug_eval )
if ( p != NULL )
{
fprintf(debug_eval_file,"attak pattern of %s is %s\n",
ColorStr[side], p->name);
fprintf(debug_eval_file,"reachable patterns: ");
for (i=0,sequence=p->sequence; i<p->n; i++,sequence=sequence->next_pattern)
if ( sequence->distance[side] != CANNOT_REACH )
fprintf(debug_eval_file,"%d ",i);
fprintf(debug_eval_file,"\n");
}
else
{
fprintf(debug_eval_file,"no attak pattern %s for %s\n",
s, ColorStr[side]);
}
#endif
}
#endif
short int
ScorePosition (register short int side)
/*
* Perform normal static evaluation of board position. A score is generated
* for each piece and these are summed to get a score for each side.
*/
{
register short int score;
register short sq, i, xside;
short int s;
short int escore;
#ifdef DEBUG_EVAL
short int d;
#endif
UpdateWeights ();
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf (debug_eval_file, "side = %d, stage = %d, in_opening = %d\n",
side, stage, in_opening_stage );
#endif
xside = side ^ 1;
hung[black] = hung[white] = pscore[black] = pscore[white] = 0;
#ifdef CACHE
#ifdef DEBUG_EVAL
if (debug_eval || !ProbeEETable (side, &s))
#else
if (!ProbeEETable (side, &s))
#endif
{
#endif
for (c1 = black; c1 <= white; c1++)
{
c2 = c1 ^ 1;
/* atk1 is array of atacks on squares by my side */
atk1 = atak[c1];
/* atk2 is array of atacks on squares by other side */
atk2 = atak[c2];
/* same for PC1 and PC2 */
PC1 = PawnCnt[c1];
PC2 = PawnCnt[c2];
for (i = PieceCnt[c1]; i >= 0; i--)
{
sq = PieceList[c1][i];
switch (board[sq])
{
case pawn:
s = PawnValue (sq, side);
break;
case knight:
s = KnightValue (sq, side);
break;
case bishop:
s = BishopValue (sq, side);
break;
case rook:
s = RookValue (sq, side);
break;
case lance:
s = LanceValue (sq, side);
break;
case silver:
s = SilverValue (sq, side);
break;
case gold:
s = GoldValue (sq, side);
break;
case ppawn:
s = PPawnValue (sq, side);
break;
case plance:
s = PLanceValue (sq, side);
break;
case pknight:
s = PKnightValue (sq, side);
break;
case psilver:
s = PSilverValue (sq, side);
break;
case pbishop:
s = PBishopValue (sq, side);
break;
case prook:
s = PRookValue (sq, side);
break;
case king:
s = KingValue (sq, side);
break;
default:
s = 0;
break;
}
pscore[c1] += s;
svalue[sq] = s;
}
}
#ifdef DEBUG_EVAL
if ( debug_eval ) {
fprintf(debug_eval_file,"pscore[black] = %d, pscore[white] = %d\n",
pscore[black], pscore[white]);
debug_svalue(debug_eval_file);
}
#endif
if (hung[side] > 1) {
#ifdef DEBUG_EVAL
if ( debug_eval ) {
fprintf(debug_eval_file,"adding %d to pscore for %d hung %d pieces.\n",
HUNGX, hung[side], side);
}
#endif
pscore[side] += HUNGX;
}
if (hung[xside] > 1) {
#ifdef DEBUG_EVAL
if ( debug_eval ) {
fprintf(debug_eval_file,"adding %d to pscore for %d hung %d pieces.\n",
HUNGX, hung[xside], xside);
}
#endif
pscore[xside] += HUNGX;
}
for (c1=black,c2=white; c1<=white; c1++,c2--)
{
#ifdef DEBUG_EVAL
short ps0 = pscore[c1];
#endif
/* Score fifth rank */
for ( sq = 36; sq <= 44; sq++ )
if ( color[sq] == c1 || atak[c1][sq] != 0 )
pscore[c1]++;
#ifdef DEBUG_EVAL
if ( debug_eval && ps0 != pscore[c1] )
fprintf(debug_eval_file,"adding %d for %s's control of 5th rank\n",
pscore[c1]-ps0, ColorStr[c1]);
ps0 = pscore[c1];
#endif
/* Score holes */
for ( sq = ((c1==black)?0:54); sq<=((c1==black)?26:80); sq++ )
if ( board[sq] == no_piece && atak[c1][sq] == 0 )
pscore[c1]--;
#ifdef DEBUG_EVAL
if ( debug_eval && ps0 != pscore[c1] )
fprintf(debug_eval_file,"adding %d for holes in %s's camp\n",
pscore[c1]-ps0, ColorStr[c1]);
#endif
/* Scoring depending whether in opening stage or not */
if ( in_opening_stage )
{
/* do not exchange bishops in ranging rook openings */
if ( GameType[c1] == RANGING_ROOK )
if ( Captured[c2][bishop] ) {
pscore[c1] += BXCHG;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for %s's bishop catched by opponent\n",
BXCHG, ColorStr[c1]);
#endif
}
}
else
{
short d1 = HasPiece[c1][silver] + HasPiece[c1][gold];
short d2 = Captured[c1][silver] + Captured[c1][gold];
pscore[c1] += (d1*2 + d2*3) * stage / 2;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"adding %d for more valuable %s generals\n",
(d1*2 + d2*3) * stage / 2, ColorStr[c1]);
#endif
}
}
#ifdef USE_PATTERN
/* Score pattern */
if ( in_opening_stage ) {
pscore[side] += ScorePatternDistance (side);
pscore[xside] += ScorePatternDistance (xside);
}
#endif
score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10;
if (dither)
{
if (flag.hash)
gsrand (starttime + (unsigned int) hashbd);
score += urand () % dither;
}
#ifdef CACHE
PutInEETable(side,score);
#endif
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf (debug_eval_file, "score = %d\n", score);
#endif
return(score);
#ifdef CACHE
}
#ifdef DEBUG_EVAL
else
{
if ( debug_eval )
fprintf (debug_eval_file, "Score cached!\n" );
}
#endif
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf (debug_eval_file, "s = %d\n", s);
#endif
return (s);
#endif
}
#define SS 1
#define RS 2
#define SR 3
#define RR 4
static
short int *PawnAdvance[2],*LanceAdvance[2],*KnightAdvance[2],
*SilverAdvance[2],*GoldAdvance[2],*BishopAdvance[2],*RookAdvance[2],
*KingAdvance[2];
inline
static
void
SetOpeningStrategy(short c, short s)
{
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"strategy for %s is ",ColorStr[c]);
#endif
if ( s == RS ) {
PawnAdvance[c] = PawnAdvanceRS;
LanceAdvance[c] = LanceAdvanceRS;
KnightAdvance[c] = KnightAdvanceRS;
SilverAdvance[c] = SilverAdvanceRS;
GoldAdvance[c] = GoldAdvanceRS;
BishopAdvance[c] = BishopAdvanceRS;
RookAdvance[c] = RookAdvanceRS;
KingAdvance[c] = KingAdvanceRS;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"Ranging vs. Static\n");
#endif
} else if ( s == SR ) {
PawnAdvance[c] = PawnAdvanceSR;
LanceAdvance[c] = LanceAdvanceSR;
KnightAdvance[c] = KnightAdvanceSR;
SilverAdvance[c] = SilverAdvanceSR;
GoldAdvance[c] = GoldAdvanceSR;
BishopAdvance[c] = BishopAdvanceSR;
RookAdvance[c] = RookAdvanceSR;
KingAdvance[c] = KingAdvanceSR;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"Static vs. Ranging\n");
#endif
} else if ( s == RR ) {
PawnAdvance[c] = PawnAdvanceRR;
LanceAdvance[c] = LanceAdvanceRR;
KnightAdvance[c] = KnightAdvanceRR;
SilverAdvance[c] = SilverAdvanceRR;
GoldAdvance[c] = GoldAdvanceRR;
BishopAdvance[c] = BishopAdvanceRR;
RookAdvance[c] = RookAdvanceRR;
KingAdvance[c] = KingAdvanceRR;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"Ranging vs. Ranging\n");
#endif
} else {
PawnAdvance[c] = PawnAdvanceSS;
LanceAdvance[c] = LanceAdvanceSS;
KnightAdvance[c] = KnightAdvanceSS;
SilverAdvance[c] = SilverAdvanceSS;
GoldAdvance[c] = GoldAdvanceSS;
BishopAdvance[c] = BishopAdvanceSS;
RookAdvance[c] = RookAdvanceSS;
KingAdvance[c] = KingAdvanceSS;
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"Static vs. Static\n");
#endif
}
}
#define AssignAdvance(b,w)\
{\
SetOpeningStrategy(black,b);\
SetOpeningStrategy(white,w);\
}
static inline void
CopyBoard (short *a, short *b, short n, short d)
{
register short *sqa, *sqb, i;
if ( n == d )
bcopy(a,b,NO_SQUARES*sizeof(short));
else
for (sqa = a,sqb = b,i=0; i<NO_SQUARES; sqa++,sqb++,i++)
if ( n == 1 )
*sqb = (*sqa) / d;
else
if ( d == 1 )
*sqb = n * (*sqa);
else
*sqb = (n * (*sqa)) / d;
}
static inline void
GuessGameType (void)
{
/*
* Try to determine the game type of "side".
*/
short side, sq, StaticRook[2] = {0,0}, RangingRook[2] = {0,0};
for ( side=black; side<=white; side++ ) {
/* static rook conditions */
if ( on_column(side,rook,7) )
StaticRook[side] += 3;
if ( on_csquare(side,pawn,34) )
StaticRook[side] += 6;
else if ( on_csquare(side,pawn,43) )
StaticRook[side] += 8;
else if ( !on_column(side,pawn,7) )
StaticRook[side] += 5;
if ( empty_square(side,5) || empty_square(side,6) )
StaticRook[side] += 2;
if ( on_left_side(side,king) )
StaticRook[side] += 2;
/* ranging rook conditions */
if ( on_left_side(side,rook) )
RangingRook[side] += 5;
else if ( !on_column(side,rook,7) )
RangingRook[side] += 3;
if ( on_csquare(side,pawn,25) )
RangingRook[side] += 1;
if ( on_csquare(side,pawn,30) )
RangingRook[side] += 1;
else
RangingRook[side] -= 2;
if ( on_right_side(side,king) )
RangingRook[side] += 2;
if ( on_csquare(side,bishop,20) )
if ( on_csquare(side,silver,11) || on_csquare(side,silver,12) ||
on_csquare(side,silver,21) )
RangingRook[side] += 3;
if ( StaticRook[side] > 5 || RangingRook[side] > 5 )
GameType[side] = (StaticRook[side] > RangingRook[side])
? STATIC_ROOK : RANGING_ROOK;
else
GameType[side] = UNKNOWN;
}
#ifdef DEBUG_EVAL
#define StringOfGameType(side)\
(GameType[side] == STATIC_ROOK ? "Static Rook" :\
(GameType[side] == RANGING_ROOK ? "Ranging Rook" : "UNKNOWN"))
if ( debug_eval )
fprintf(debug_eval_file,"guessing game type: %s vs. %s\n",
StringOfGameType(black), StringOfGameType(white));
#endif
if ( GameType[black] == UNKNOWN || GameType[white] == UNKNOWN )
{
for (side = black; side <= white; side++)
if ( side == computer && GameType[side] == UNKNOWN ) {
/*
* Game type is UNKNOWN.
* Make a decision what type of game to play.
* To make computer games more interesting, make a
* random decision.
*/
if ( !on_csquare(side,pawn,25) ) {
/* Play static rook if rook pawn has been pushed! */
GameType[side] = STATIC_ROOK;
} else {
unsigned int random = urand () % 100;
short d = StaticRook[side] - RangingRook[side];
switch ( GameType[side ^ 1] ) {
case STATIC_ROOK:
if ( random < 35 + d ) GameType[side] = STATIC_ROOK;
else if ( random < 95 ) GameType[side] = RANGING_ROOK;
break;
case RANGING_ROOK:
if ( random < 75 + d) GameType[side] = STATIC_ROOK;
else if ( random < 95 ) GameType[side] = RANGING_ROOK;
break;
default:
if ( random < 33 + d) GameType[side] = STATIC_ROOK;
else if ( random < 66 ) GameType[side] = RANGING_ROOK;
}
}
#ifdef DEBUG_EVAL
if ( debug_eval )
fprintf(debug_eval_file,"decide game type: %s vs. %s\n",
StringOfGameType(black), StringOfGameType(white));
#endif
}
}
}
#ifdef DEBUG_EVAL
#define StringOfGameType(side)\
(GameType[side] == STATIC_ROOK ? "Static Rook" :\
(GameType[side] == RANGING_ROOK ? "Ranging Rook" : "UNKNOWN"))
#endif
void
ExaminePosition (void)
/*
* This is done one time before the search is started. Set up arrays Mwpawn,
* Mbpawn, Mknight, Mbishop, Mking which are used in the SqValue() function
* to determine the positional value of each piece.
*/
{
register short i, sq, msq;
register short fyle;
short wpadv, bpadv, z, side, pp, j, k, val, Pd, rank;
ataks (black, atak[black]);
ataks (white, atak[white]);
#ifdef DEBUG_EVAL
if ( debug_eval ) {
debug_position (debug_eval_file);
/* debug_ataks (debug_eval_file); */
}
#endif
UpdateWeights ();
#ifdef NOMEMSET
{ short c, p;
for ( c = black; c <= white; c++ )
for ( p = pawn; p <= king; p++ )
HasPiece[c][p] = 0;
}
#else
memset ((char *)HasPiece, 0,(unsigned long)sizeof(HasPiece));
#endif
for (side = black; side <= white; side++)
for (i = PieceCnt[side]; i >= 0; i--)
++HasPiece[side][board[PieceList[side][i]]];
GuessGameType();
#ifdef USE_PATTERN
if ( in_opening_stage ) {
for (side = black; side <= white; side++)
UpdatePatterns (side, GameCnt);
}
#endif
if ( GameType[black] == STATIC_ROOK) {
if ( GameType[white] == STATIC_ROOK ) {
/* STATIC vs. STATIC */
AssignAdvance(SS,SS);
} else if ( GameType[white] == RANGING_ROOK ) {
/* STATIC vs. RANGING */
AssignAdvance(SR,RS);
} else {
/* STATIC vs. ??? */
AssignAdvance(SS,SS);
}
} else if ( GameType[black] == RANGING_ROOK ) {
if ( GameType[white] == STATIC_ROOK ) {
/* RANGING vs. STATIC */
AssignAdvance(RS,SR);
} else if ( GameType[white] == RANGING_ROOK ) {
/* RANGING vs. RANGING */
AssignAdvance(RR,RR);
} else {
/* RANGING vs. ???? */
AssignAdvance(RS,SR);
}
} else {
if ( GameType[white] == STATIC_ROOK ) {
/* ???? vs. STATIC */
AssignAdvance(SS,SS);
} else if ( GameType[white] == RANGING_ROOK ) {
/* ???? vs. RANGING */
AssignAdvance(SR,RS);
} else {
/* ???? vs. ???? */
AssignAdvance(SS,SS);
}
}
/* Weighted advance tables. Can be updated. */
CopyBoard (PawnAdvance[black], Mpawn[black], PADVNCM, 10);
CopyBoard (PawnAdvance[white], Mpawn[white], PADVNCM, 10);
CopyBoard (SilverAdvance[black], Msilver[black], SADVNCM, 10);
CopyBoard (SilverAdvance[white], Msilver[white], SADVNCM, 10);
CopyBoard (GoldAdvance[black], Mgold[black], GADVNCM, 10);
CopyBoard (GoldAdvance[white], Mgold[white], GADVNCM, 10);
CopyBoard (KingAdvance[black], Mking[black], KADVNCM, 1);
CopyBoard (KingAdvance[white], Mking[white], KADVNCM, 1);
/* Tables without weighted advances. Must not be updated! */
for ( side = black; side <= white; side++ ) {
Mlance[side] = LanceAdvance[side];
Mknight[side] = KnightAdvance[side];
Mbishop[side] = BishopAdvance[side];
Mrook[side] = RookAdvance[side];
}
#ifdef DEBUG_EVAL
if ( debug_eval ) {
fprintf(debug_eval_file,"relative pawn table weigth: %d\n",PADVNCM);
fprintf(debug_eval_file,"relative silver table weigth: %d\n",SADVNCM);
fprintf(debug_eval_file,"relative gold table weigth: %d\n",GADVNCM);
fprintf(debug_eval_file,"relative king table weigth: %d\n",KADVNCM);
}
#endif
/* Build up weighted enemy-king distance tables. */
if ( KATAK == 0 )
#if defined(NOMEMSET) || defined(MSDOS)
for (sq = 0; sq < NO_SQUARES; sq++)
Kfield[black][sq] = Kfield[white][sq] = 0;
#else
memset ((char *) Kfield, 0, (unsigned long)sizeof (Kfield));
#endif /* NOMEMSET */
else
for (sq = 0; sq < NO_SQUARES; sq++)
{
Kfield[black][sq] = (distance(sq,WhiteKing)==1) ? KATAK : 0;
Kfield[white][sq] = (distance(sq,BlackKing)==1) ? KATAK : 0;
}
#ifdef DEBUG_EVAL
if ( debug_eval )
for (side=black; side<=white; side++)
{
fprintf(debug_eval_file,"%s's pawn table\n\n",ColorStr[side]);
debug_table(debug_eval_file,Mpawn[side]);
fprintf(debug_eval_file,"%s's silver table\n\n",ColorStr[side]);
debug_table(debug_eval_file,Msilver[side]);
fprintf(debug_eval_file,"%s's gold table\n\n",ColorStr[side]);
debug_table(debug_eval_file,Mgold[side]);
fprintf(debug_eval_file,"%s's king table\n\n",ColorStr[side]);
debug_table(debug_eval_file,Mking[side]);
fprintf(debug_eval_file,"%s's distance to enemy king table\n\n",ColorStr[side]);
debug_table(debug_eval_file,Kfield[side]);
}
#endif
}
void
UpdateWeights (void)
/*
* If material balance has changed, determine the values for the positional
* evaluation terms.
*/
{
register short s1, dio, io, os;
emtl[black] = mtl[black] - pmtl[black] - valueK;
emtl[white] = mtl[white] - pmtl[white] - valueK;
tmtl = emtl[black] + emtl[white];
behind_in_material[black] = ((mtl[white] - mtl[black]) > valueB);
behind_in_material[white] = ((mtl[black] - mtl[white]) > valueB);
/* GameCnt = number of half moves */
if (GameCnt < 21)
s1 = 0; /* 0 <= GameCnt <= 20: stage = 0 */
else if (GameCnt < 41)
s1 = 1 + (GameCnt-20)/3; /* 21 <= GameCnt <= 40: stage = 1..7 */
else if (GameCnt < 61)
s1 = 8 + (GameCnt-40)/5; /* 41 <= GameCnt <= 60: stage = 8..11 */
else
s1 = 12 + (GameCnt-60)/7;
if (s1 != stage)
{
stage = stage2 = s1;
os = (GameType[black] == STATIC_ROOK && GameType[white] == STATIC_ROOK) ? 10 : 8;
dio = (in_opening_stage = io = (s1 < os)) ? (os - s1) : 0;
PADVNCM = io?12+s1:1; /* advanced pawn multiplier */
PMBLTY = 5; /* pawn mobility */
PSTRONG = 3; /* pawn supported by rook/lance */
BDCLOSED = -(dio*2); /* bishops diagonal closed by pawn */
P2STRONG = 20; /* attacking pawn on 2nd col is strong */
LHOPN = -4; /* no own pawn on lance file ahead */
LHOPNX = 4; /* no enemy pawn on lance file ahead */
LPROTECT = 6; /* protect own piece with lance */
LDNGR = -4; /* lance is in danger */
LXRAY = 8; /* lance Xray attack on piece */
NDNGR = -4; /* knight is in danger */
KNIGHTPOST = 2; /* knight near enemy pieces */
KNIGHTSTRONG = 2; /* occupies pawn hole */
SADVNCM = io?15+s1:1; /* advanced silver multiplier */
SBEFOREG = 2; /* proverb: silver before gold */
GADVNCM = io?14+s1:1; /* advanced gold multiplier */
BISHOPSTRONG = 4; /* occupies pawn hole */
BHCLSD = -3; /* first or second piece in a bishop's direction is an own pawn */
BHCLSDX = -2; /* first or second piece in a bishop's direction is an opponents pawn */
BRXRAY = 10; /* bishop or rook Xray attack on piece */
BXCHG = -10; /* bishop exchange in ranging rook opening */
RHOPN = 10; /* no own pawn on rook file ahead */
RHOPNX = 8; /* no enemy pawn on rook file ahead */
R2NDCOL = dio*2; /* rook is on 2nd column */
PINVAL = 15; /* Pin */
KADVNCM = io?1+s1:0; /* advanced king multiplier */
KHOPN = -8; /* no own pawn in kings file */
KHOPNX = KHOPN * 2; /* no opponents pawn in kings file */
KCASTLD = 20; /* king protected by castle */
KMOVD = 4; /* proverb: a sitting king is a sitting duck */
KATAK = io ? 1 : 8; /* B,R,L attacks near enemy king */
KSFTY = 4; /* king safety */
OPENOK = dio*2; /* corresponding to opening pattern */
OPENWRONG = -dio*3; /* not correpsonding */
KINGOD = 2+s1/4; /* distance to own king multiplier */
KINGED = 3+s1/4; /* distance to enemy king multiplier */
PROMD = 2+s1/4; /* distance to promotion zone multiplier */
ATAKD = -15; /* defender > attacker */
HUNGP = -14; /* each hung piece */
HUNGX = -18; /* extra for >1 hung piece */
#ifdef USE_PATTERN
PATTACK = dio; /* attack pattern distance multiplier */
PCASTLE = dio; /* castle pattern distance multiplier */
#endif
}
}